﻿using System;
using System.Diagnostics;
using System.Windows;
using Sinacor.Infra.UI.Controls.SmartClient;
using Sinacor.UI.Application.Settings.SmartClient;
using Sinacor.UI.HelpViewer.View;
using System.Configuration;
using System.Threading;
using Sinacor.Infra.UI.Messaging;
using Sinacor.Infra.UI.Exceptions;
using Sinacor.Infra.Common.Exceptions;
using System.Collections.Generic;
using PSE.Framework.ErrorLogging;
using PSE.Framework.UI.Resources;

namespace Sinacor.UI.HelpViewer.Application
{
    class SinacorHelpApplication : System.Windows.Application
    {
        /// <summary>
        /// Atributo privado da classe MessageManager
        /// </summary>
        private MessageManager _messageManager;

        /// <summary>
        /// Constructor da Aplicação
        /// Responsável em definir os eventos da aplicação.
        /// </summary>
        public SinacorHelpApplication()
        {
            //Inicializa o MessageManager para receber mensagens da aplicação.
            _messageManager = MessageManager.GetInstance();

            // Registra o EventHandler do Startup
            this.Startup += new StartupEventHandler(SinacorHelpApplication_Startup);
            
            // Registra o EventHandler ao Sair da Aplicação.
            this.Exit += new ExitEventHandler(SinacorHelpApplication_Exit);

            // Registra o EventHandler para exceções não tratadas.
            this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(SinacorHelpApplication_DispatcherUnhandledException);
        }

        /// <summary>
        /// Método disparado ao inicializar a aplicação
        /// </summary>
        /// <param name="sender">objeto que gerou o evento</param>
        /// <param name="e">parametros do evento.</param>
        private void SinacorHelpApplication_Startup(object sender, StartupEventArgs e)
        {
            // Cria application settings
            ApplicationSettings applicationSettings = ApplicationSettings.GetInstance();

            // Carregando os settings locais da aplicação
            applicationSettings.BeginInit();

            // Verifica se já não existe um processo do sinacor sendo executado
            if (ExistsSinacorProcess())
            {
                // Exibe mensagem e encerra aplicativo
                SinacorMessageBox.Show((string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.Application.Message.ApplicationAlreadyStarted"),
                                       (string)ResourceProviderManager.GetResourceProvider().TryGetResource("Infra.Controls.Label.DefaultMessageBoxTitle"),
                                       SinacorMessageBoxButton.Ok,
                                       SinacorMessageBoxImage.Error);

                //Finaliza a aplicação
                ForceCloseApplication();
                return;
            }

            // Carregando os settings remotos da aplicação
            applicationSettings.EndInit();

            Viewer _viewer = new Viewer();
            _viewer.ShowDialog();

            ForceCloseApplication();
        }
        
        /// <summary>
        /// Finaliza a aplicação mesmo se existirem alterações não salvas nas telas.
        /// </summary>
        private void ForceCloseApplication()
        {
            this.Shutdown();
        }

        /// <summary>
        /// Método disparado ao ocorrer uma exceção na camada da aplicação ( View )
        /// Responsável por apresentar a mensagem de erro ao usuário
        /// e finalizar a aplicação.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SinacorHelpApplication_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            HandleException(e.Exception);
            
            ForceCloseApplication();

            e.Handled = true;
        }

        /// <summary>
        /// Método disparado ao finalizar a aplicação.
        /// </summary>
        /// <param name="sender">objeto que gerou o evento</param>
        /// <param name="e">parametros do evento.</param>
        void SinacorHelpApplication_Exit(object sender, ExitEventArgs e)
        {
            if (_messageManager != null)
                _messageManager.Dispose();
            
            _messageManager = null;
        }

        /// <summary>
        /// Verifica se já existe um processo do Sinacor.exe
        /// </summary>
        private static bool ExistsSinacorProcess()
        {
            Process[] processList = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
            if (processList.Length > 1)
                return true;

            return false;
        }

        internal static void HandleException(Exception ex)
        {
            string message;

            ErrorMessage.ConfigureExceptionMessage(ex);

            message = (string)ResourceProviderManager.GetResourceProvider().TryGetResource("Common.ExceptionMessage.ApplicationFailed");

            if (ex is ValidationException ||
                ex is BaseErrorNumberException)
            {
                message += Environment.NewLine + ex.Message;
            }

            Uri sourceAddress = null;
            Dictionary<string, object> extensionData = null;

            if (ex is BaseLogException &&
                ((BaseLogException)ex).SourceAddress != null &&
                !string.IsNullOrEmpty(((BaseLogException)ex).LogData))
            {
                sourceAddress = ((BaseLogException)ex).SourceAddress;
                extensionData = new Dictionary<string, object>() { { "InnerLogData", ((BaseLogException)ex).LogData } };
            }

            LogData logData = Sinacor.Infra.UI.ErrorLogging.ErrorLogger.WriteLog(LogType.Error, ex, extensionData);

            SinacorMessageBox.ShowError(message, sourceAddress, logData);
        }
    }
}
